/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  EventEmitter,
  Input,
  OnInit,
  Output,
  TemplateRef,
  ViewChild
} from '@angular/core';
import { MenuItem, TreeNode } from '@iux/live';
import { extendFileSystemNodeParams, I18NService } from 'app/shared';
import { FileSystemResponseList } from 'app/shared/api/models';
import { CopyControllerService } from 'app/shared/api/services';
import {
  CAPACITY_UNIT,
  CommonConsts,
  RestoreFileType
} from 'app/shared/consts';
import {
  assign,
  cloneDeep,
  each,
  find,
  first,
  includes,
  isArray,
  isEmpty,
  map,
  reject,
  size,
  some,
  take,
  trim
} from 'lodash';
import {
  ProTableComponent,
  TableCols,
  TableConfig,
  TableData
} from '../pro-table';
import { finalize } from 'rxjs/operators';

@Component({
  selector: 'aui-file-level-window',
  templateUrl: './file-level-window.component.html',
  styleUrls: ['./file-level-window.component.less'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class FileLevelWindowComponent implements OnInit {
  @Input() copy;
  @Output() tableSelectionChange = new EventEmitter<any>();

  restoreFileType = RestoreFileType;
  unitconst = CAPACITY_UNIT;
  _includes = includes;

  totalView = 'all';
  selectedView = 'selected';
  pathView = this.totalView;
  total = 0;
  selectedTotal = 0;
  filePathItems: MenuItem[] = [];
  hideItems = [];
  maxBreadNum = 5;

  // 右边表格
  tableData: TableData;
  tableConfig: TableConfig;
  selectionTableData = [];
  selectTableData: TableData;
  selectTableConfig: TableConfig;
  tableLoading = false;

  // 搜索关键字
  searcKey: string;

  // 文件目录内容
  treeData: TreeNode[] = [];
  selectionTree = [];

  // 初始页
  startPage = CommonConsts.PAGE_START;
  // 默认排序
  orders = [];
  // 查询下一页需要上一页最后一条数据的sort值
  searchAfter = [];
  // 接口锁定，锁定时不再触发同一接口
  lockFileRequest = false;
  // 搜索是否超过1000条
  searchMax = false;
  // 是否已查询完毕的标识
  hasQueryAll = false;

  @ViewChild('dataTable', { static: false }) dataTable: ProTableComponent;
  @ViewChild('dataSelectTable', { static: false })
  dataSelectTable: ProTableComponent;
  @ViewChild('fileTpl', { static: true }) fileTpl: TemplateRef<any>;
  @ViewChild('sizeTpl', { static: true }) sizeTpl: TemplateRef<any>;
  @ViewChild('optTpl', { static: true }) optTpl: TemplateRef<any>;

  constructor(
    private i18n: I18NService,
    private cdr: ChangeDetectorRef,
    private copyControllerService: CopyControllerService
  ) {}

  ngOnInit(): void {
    this.initTreeData();
    this.initTableConfig();
  }

  // 滚动到底部，触发查询下一页
  scrollEnd() {
    if (!this.hasQueryAll && !this.lockFileRequest) {
      this.startPage++;
      this.lockFileRequest = true;
      this.getTableData(first(this.selectionTree), true);
    }
  }

  initTableConfig() {
    const cols: TableCols[] = [
      {
        key: 'size',
        name: this.i18n.get('common_size_label'),
        cellRender: this.sizeTpl
      },
      {
        key: 'modifyTime',
        name: this.i18n.get('protection_last_modifyed_label'),
        sort: true
      },
      {
        key: 'rootPath',
        name: this.i18n.get('common_path_label')
      }
    ];
    const page: any = {
      mode: 'simple',
      pageSizeOptions: [20, 50, 100, 200]
    };
    this.tableConfig = {
      table: {
        async: false,
        compareWith: 'rootPath',
        columns: [
          {
            key: 'path',
            name: this.i18n.get('common_name_label'),
            cellRender: this.fileTpl,
            sort: true
          },
          ...cols
        ],
        rows: {
          selectionMode: 'multiple',
          selectionTrigger: 'selector',
          showSelector: true
        },
        scroll: { y: '530px' },
        virtualScroll: true,
        colDisplayControl: false,
        selectionChange: selection => {
          this.selectionTableData = selection;
          this.setSelection();
        },
        scrollEnd: () => this.scrollEnd(),
        customSortChange: sort => {
          this.resetQueryStatus();
          this.orders = [(sort.direction === 'asc' ? '+' : '-') + sort.key];
          this.tableData = {
            data: [],
            total: 0
          };
          this.total = 0;
          this.getTableData(first(this.selectionTree));
        },
        trackByFn: (_, item) => {
          return item.rootPath;
        }
      },
      pagination: null
    };
    this.selectTableConfig = {
      table: {
        compareWith: 'rootPath',
        async: false,
        columns: [
          {
            key: 'path',
            name: this.i18n.get('common_name_label'),
            cellRender: this.fileTpl,
            sort: true,
            filter: {
              type: 'search',
              filterMode: 'contains'
            }
          },
          ...take(cols, 2),
          {
            key: 'rootPath',
            name: this.i18n.get('common_path_label'),
            cellRender: this.optTpl
          }
        ],
        scroll: { y: '520px' },
        colDisplayControl: false,
        trackByFn: (_, item) => {
          return item.rootPath;
        }
      },
      pagination: page
    };
  }

  initTreeData() {
    if (isEmpty(this.copy)) {
      return;
    }
    this.treeData = [
      {
        name: '',
        children: [],
        path: '/',
        label: this.copy.resource_name,
        rootPath: '/',
        contentToggleIcon: 'aui-icon-directory'
      }
    ];
    this.selectionTree = [first(this.treeData)];
    // 默认查询根路径
    this.getFilePathItems(this.selectionTree[0]);
    // 默认选中子节点
    setTimeout(() => {
      this.pathNodeCheck({ node: this.selectionTree[0] });
    });
  }

  // 获取当前选中节点
  findNodeFromPath(node, path) {
    if (node.path === path || (node.path === '/' && !path)) {
      return node;
    }
    if (!isEmpty(node.parent)) {
      return this.findNodeFromPath(node.parent, path);
    }
  }

  // 点击面包屑路径跳转
  toTargetPath($event, node, clickPath) {
    if ($event.event?.stopPropagation) {
      $event.event.stopPropagation();
    }
    //选中的是当前激活节点，直接返回
    if (node.path === clickPath) {
      return;
    }
    const findNode = this.findNodeFromPath(node, clickPath);
    if (!isEmpty(findNode)) {
      this.pathNodeCheck({ node: findNode });
      this.selectionTree = [findNode];
    }
  }

  // 获取面包屑路径
  getFilePathItems(node) {
    const path = node?.rootPath;
    if (!path) {
      this.filePathItems = [];
      return;
    }
    const breadcrumbItems = [];
    const pathItems = path === '/' ? [''] : path.split('/');
    each(pathItems, (item, index) => {
      breadcrumbItems.push({
        id: `${index}_${item}`,
        label: item || this.copy?.resource_name,
        onClick: event => this.toTargetPath(event, node, item)
      });
    });
    this.filePathItems = [...breadcrumbItems];
    if (this.filePathItems?.length > this.maxBreadNum) {
      const hideItem = this.filePathItems.splice(
        this.maxBreadNum - 2,
        this.filePathItems.length - this.maxBreadNum + 1
      );
      this.hideItems = [...hideItem];
      this.filePathItems.splice(this.maxBreadNum - 2, 0, {
        id: 'more_bread',
        label: '...',
        items: this.hideItems
      });
    } else {
      this.hideItems = [];
    }
    this.filePathItems = [...this.filePathItems];
  }

  updataChildren(res: FileSystemResponseList, node) {
    each(res.records, (item: any) => {
      item = extendFileSystemNodeParams(item);
    });
    if (isArray(node.children) && !isEmpty(node.children)) {
      node.children = [
        ...reject(node.children, n => {
          return n.isMoreBtn;
        }),
        ...res.records
      ];
    } else {
      node.children.push(...res.records);
    }
    if (res.totalCount > size(node.children)) {
      const moreClickNode = {
        label: `${this.i18n.get('common_more_label')}...`,
        contentToggleIcon: '',
        isMoreBtn: true,
        hasChildren: false,
        isLeaf: true,
        children: null,
        parent: node,
        startPage: Math.floor(size(node.children) / CommonConsts.MAX_PAGE_SIZE)
      };
      node.children = [...node.children, moreClickNode];
    }
    this.treeData = [...this.treeData];
  }

  getFileData(node, startPage = CommonConsts.PAGE_START) {
    const params = {
      copyId: this.copy.uuid,
      pageNo: startPage,
      pageSize: CommonConsts.MAX_PAGE_SIZE,
      parentPath: node.rootPath || '/',
      akOperationTips: false,
      akLoading: false
    };
    if (!isEmpty(this.copy.device_esn)) {
      assign(params, { memberEsn: this.copy.device_esn });
    }
    // 已索引的副本，请求下一页需要传上一页最后一条数据的sort值
    const sortValue = node.children[node.children.length - 2]?.sort;
    if (params.pageNo > 0 && !isEmpty(sortValue)) {
      assign(params, {
        searchAfter: sortValue
      });
    }
    node.isLoading = true;
    this.treeData = [...this.treeData];
    this.copyControllerService.ListCopyCatalogs(params).subscribe({
      next: res => {
        node.isLoading = false;
        this.updataChildren(res, node);
        this.cdr.detectChanges();
      },
      error: () => {
        node.isLoading = false;
        this.treeData = [...this.treeData];
        this.cdr.detectChanges();
      }
    });
  }

  tabChange() {
    if (this.pathView === this.totalView) {
      setTimeout(() => {
        this.dataTable?.setSelections(this.selectionTableData);
      });
    }
  }

  // 通过文件名搜索。
  searchName(name: string) {
    this.resetQueryStatus();
    if (this.pathView === this.totalView) {
      this.getTableData({
        ...first(this.selectionTree),
        searrchByName: trim(name)
      });
    }
  }

  // 展开树节点
  expandedChange(node, isMoreBtn = false) {
    const moreBtn = find(node.children, { isMoreBtn: true });
    if ((!!size(node.children) && !isMoreBtn) || node.expand) {
      return;
    }
    this.getFileData(node, moreBtn?.startPage);
  }

  updateTable(res, byScroll = false) {
    each(res.records, (item: any) => {
      item = extendFileSystemNodeParams(item);
    });

    // 如果是通过滚动加载，需要把数据合并，否则不用
    if (byScroll) {
      this.tableData = {
        data: [...this.tableData.data, ...res.records],
        total: res.totalCount,
        keepScroll: true
      };
    } else {
      this.tableData = {
        data: res.records,
        total: res.totalCount
      };
    }
    this.total = res.totalCount;
  }

  // 更新标记和查询状态
  updateSort(records, totalCount) {
    // 记录最后一条数据的sort
    this.searchAfter = records[records.length - 1]?.sort;
    // 记录是否已经查询完，滚动是否还需要查询
    this.hasQueryAll =
      this.startPage === Math.floor(totalCount / CommonConsts.PAGE_SIZE_MAX);
  }

  // 获取指定路径下的文件
  getTableData(node, byScroll = false) {
    if (!node) {
      node = first(this.selectionTree);
    }
    if (!node || node.isLeaf) {
      this.tableData = {
        data: [],
        total: 0
      };
      this.total = 0;
      return;
    }
    if (trim(node.searrchByName) || trim(this.searcKey)) {
      const params = {
        copyId: this.copy.uuid,
        pageNum: this.startPage,
        pageSize: CommonConsts.PAGE_SIZE_MAX,
        parentPath: node.rootPath || '/',
        name: trim(this.searcKey),
        akLoading: false,
        searchType: 'recursive'
      };
      // 已索引的副本翻页时需要传上一条的sort
      if (byScroll && !isEmpty(this.searchAfter)) {
        assign(params, {
          searchAfter: this.searchAfter
        });
      }
      if (!isEmpty(this.copy.device_esn)) {
        assign(params, { memberEsn: this.copy.device_esn });
      }
      this.tableLoading = true;
      this.copyControllerService
        .ListCopyCatalogsByName(params)
        .pipe(
          finalize(() => {
            this.tableLoading = false;
            this.lockFileRequest = false;
            this.cdr.detectChanges();
          })
        )
        .subscribe(res => {
          this.searchMax = res.totalCount >= 1000;
          // 更新查询滚动查询状态
          this.updateSort(res.records, res.totalCount);
          this.updateTable(res, byScroll);
          this.cdr.detectChanges();
        });
    } else {
      this.searchMax = false;
      const params = {
        copyId: this.copy.uuid,
        pageNo: this.startPage,
        pageSize: CommonConsts.PAGE_SIZE_MAX,
        parentPath: node.rootPath || '/',
        akLoading: false
      };
      // 已索引的副本翻页时需要传上一条的sort
      if (byScroll && !isEmpty(this.searchAfter)) {
        assign(params, {
          searchAfter: this.searchAfter
        });
      }
      if (!isEmpty(this.copy.device_esn)) {
        assign(params, { memberEsn: this.copy.device_esn });
      }
      if (!isEmpty(this.orders)) {
        assign(params, {
          orders: this.orders
        });
      }
      this.tableLoading = true;
      this.copyControllerService
        .ListCopyCatalogs(params)
        .pipe(
          finalize(() => {
            this.tableLoading = false;
            this.lockFileRequest = false;
            this.cdr.detectChanges();
          })
        )
        .subscribe(res => {
          // 更新查询滚动查询状态
          this.updateSort(res.records, res.totalCount);
          this.updateTable(res, byScroll);
          this.cdr.detectChanges();
        });
    }
  }

  // 重置标记和查询状态
  resetQueryStatus() {
    this.searchAfter = [];
    this.startPage = CommonConsts.PAGE_START;
    this.orders = [];
    this.hasQueryAll = false;
    this.lockFileRequest = false;
  }

  // 点击左树节点
  pathNodeCheck($event) {
    const node = $event.node;
    this.getFilePathItems(node);
    // 重置页码和状态
    this.resetQueryStatus();
    // 获取右边表格数据，当前路径下子路径
    if (this.pathView === this.totalView) {
      this.getTableData(node);
    } else {
      this.pathView = this.totalView;
      setTimeout(() => {
        this.getTableData(node);
        this.dataTable?.setSelections(this.selectionTableData);
      });
    }
    if (!node.isLeaf) {
      this.expandedChange(node);
    }
  }

  beforeSelected = item => {
    if (this.selectionTree[0].rootPath === item.rootPath) {
      return false;
    }
  };

  // 树结构点击更多按钮，显示更多目录
  clickMoreFile($event, item) {
    if ($event.stopPropagation) {
      $event.stopPropagation();
    }
    this.expandedChange(item.parent, true);
  }

  // 如果父节点选了，子节点选中自动忽略
  mergeSelection() {
    let mergePaths = [];
    let rootPaths = map(this.selectionTableData, 'rootPath');
    mergePaths = reject(this.selectionTableData, item => {
      return (
        includes(rootPaths, item.parentPath) ||
        some(rootPaths, rootPath => includes(item.parentPath, `${rootPath}/`))
      );
    });
    return mergePaths;
  }

  // 设置选中项
  setSelection() {
    const mergePaths = this.mergeSelection();
    this.selectedTotal = size(mergePaths);
    this.selectTableData = {
      data: mergePaths,
      total: this.selectedTotal
    };
    this.tableSelectionChange.emit(cloneDeep(mergePaths));
  }

  // 删除选中的目录
  deleteNode(node) {
    this.selectionTableData = reject(
      this.selectionTableData,
      item => item.rootPath === node.rootPath
    );
    this.setSelection();
  }
}
